#include "Grammar.h"
#include "Utility.h"
using namespace std;
Grammar::Grammar()
{
	
}

void Grammar::init(string lSystemFile)
{
	readFile(lSystemFile);
}



void Grammar::reset()
{
	len = 0;
	iter = 0;
	xrot = 0.0f;
	yrot = 0.0f;
	zrot = 0.0f;
	reps.clear();
	start.clear();
	rules.clear();
}

float Grammar::getXRot()
{
	return xrot;
}

float Grammar::getYRot()
{
	return yrot;
}

float Grammar::getZRot()
{
	return zrot;
}

int Grammar::getLen()
{
	return len;
}

void Grammar::readFile(string sfileName)
{
	//clear
	reset();

	//open file
	const char* fileName = sfileName.c_str();
	fstream inStream;
	inStream.open(fileName,ios::in); //open file
	if(inStream.fail())
	{
		cout<<"file open failure!"<<endl;
		return;
	}

	//read file
	string line;
	vector<string> splittedString;

	//read comments
	getline(inStream,line);
	while(line[0] == '#')
	{
		getline(inStream,line);
	}

	//read len
	splittedString.clear();
	splittedString = Utility::split(line,": ");
	len = atoi(splittedString[1].c_str());

	//read iter
	getline(inStream,line);
	splittedString.clear();
	splittedString = Utility::split(line,": ");
	iter = atoi(splittedString[1].c_str());

	//read rot
	getline(inStream,line);
	splittedString.clear();
	splittedString = Utility::split(line,": ");
	line = splittedString[1];
	splittedString.clear();
	splittedString = Utility::split(line," ");
	xrot = atof(splittedString[0].c_str());
	yrot = atof(splittedString[1].c_str());
	zrot = atof(splittedString[2].c_str());

	//read reps
	getline(inStream,line);
	splittedString.clear();
	splittedString = Utility::split(line,": ");
	while(splittedString[0] == "rep")
	{
		//add rep
		line = splittedString[1];
		splittedString.clear();
		splittedString = Utility::split(line,",");
		//"" bug solution
		if(splittedString.size() == 2 && splittedString[1]!="")
		{
			reps.insert(pair<char,char> (splittedString[0][0],splittedString[1][0]));
		}
		else 
		{
			reps.insert(pair<char,char> (splittedString[0][0],' '));
		}

		//read another rep
		getline(inStream,line);
		splittedString.clear();
		splittedString = Utility::split(line,": ");
	}

	//read start
	start = splittedString[1];

	//read rules
	while(!inStream.eof())
	{
		getline(inStream,line);
		splittedString.clear();
		//eof bug solution
		if(line.find(": ")==-1)
			break;

		splittedString = Utility::split(line,": ");
		rules.insert(pair<char,string> (splittedString[0][0],splittedString[1]));
	}

	//close
	inStream.close();

	//debug
	cout<<"Grammar file: "<<fileName<<endl;
	cout<<"len = "<<len<<"; iter = "<<iter<<";"<<endl;
	cout<<"xrot = "<<xrot<<"; yrot = "<<yrot<<"; zrot = "<<zrot<<endl;
	cout<<"reps: "<<reps.size()<<endl;
	for(map<char,char>::iterator it= reps.begin();it!=reps.end();it++)
	{
		cout<<"rep: "<<it->first<<","<<it->second<<endl;
	}
	cout<<"start: "<<start<<endl;
	cout<<"rules: "<<rules.size()<<endl;
	for(map<char,string>::iterator it = rules.begin();it!=rules.end();it++)
	{
		cout<<it->first<<": "<<it->second<<endl;
	}

}

string Grammar::rewrite()
{
	string turtleString = start;

	//rules iteration
	for(int iterTime = 0;iterTime<iter;iterTime++)
	{
		int index = 0;
		while(index != turtleString.size())
		{
			for(map<char,string>::iterator it = rules.begin();it!=rules.end();it++)
			{
				if(turtleString[index] == it->first)
				{
					turtleString.replace(index,1,it->second);
					index+=it->second.size()-1;
					break;
				}
			}
			index++;
		}

	}

	//debug
	//cout<<"iteration: "<<iter<<endl;
	//cout<<"turtle string after rules iteration: "<<turtleString<<endl;

	//replace
	int index = 0;
	while(index!=turtleString.size())
	{
		for(map<char,char>::iterator it= reps.begin();it!=reps.end();it++)
		{
			if(turtleString[index] == it->first)
			{
				if(it->second == ' ')
				{
					turtleString.erase(index,1);
					index--;
				}
				else
				{
					turtleString[index] = it->second;
				}
			break;
			}
		}
		index++;
	}
	
	//debug
	//cout<<"turtle string after rep: "<<turtleString<<endl;

	return turtleString;
}